package com.meta.func.service.impl;

import com.meta.cache.NdCacheService;
import com.meta.common.CommonInfo;
import com.meta.common.ConstDef;
import com.meta.func.bo.InitFdParam;
import com.meta.func.bo.InitFilterParam;
import com.meta.func.service.FilterFuncService;
import com.meta.layout.service.LayoutService;
import com.meta.nd.annotation.utils.NdAnnotationUtil;
import com.meta.nd.filter.bo.FilterDef;
import com.meta.nd.filter.vo.FilterFd;
import com.meta.nd.filter.vo.ResultFd;
import com.meta.nd.service.NvService;
import com.meta.nd.util.NvTool;
import com.meta.nd.vo.Fd;
import com.meta.nd.vo.Nd;
import com.meta.nd.vo.Nv;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

@Transactional
@Service
public class FilterFuncServiceImpl implements FilterFuncService {
    @Resource
    NdCacheService ndCacheService;
    @Resource
    LayoutService layoutService;
    @Resource
    NvService nvService;

    @Override
    public InitFilterParam initFilterFuncParam(String targetNdCode, String returnNdCode,String postfix) {
        if (StringUtils.isEmpty(targetNdCode))
            throw new RuntimeException("初始查询功能创建，目标ndCode不能为空！");
        Nd nd = ndCacheService.getNdRequired(targetNdCode);
        if ( StringUtils.isEmpty(returnNdCode))
            returnNdCode = nd.getNdCode();
        if ( postfix == null)
            postfix = "";
        InitFilterParam initFilterParam = new InitFilterParam(targetNdCode,returnNdCode,postfix);
        initFilterParam.setCode(nd.getNdCode()+"F" + postfix);
        initFilterParam.setName(nd.getNdName()+"F" + postfix);
        initFilterParam.setDescription(nd.getNdDescription()+"查询");
        initFilterParam.initAllFds(nd);
        return initFilterParam;
    }

    @Transactional
    @Override
    public Nv commitFilterFunc(InitFilterParam initFilterParam) {
        if (StringUtils.isEmpty(initFilterParam.getNdCode()))
            throw new RuntimeException("初始查询功能创建的目标ndCode不能为空！");
        Nd rootNd = ndCacheService.getNdRequired(initFilterParam.getNdCode());
        Nd returnNd = rootNd.findNdByNdCode(initFilterParam.getReturnNdCode());
        if ( returnNd == null)
            throw new RuntimeException("初始查询功能创建返回的ndCode不能为空！");
        Nd conditionNd = createConditionNd(rootNd, returnNd, initFilterParam);
        Nd resultNd = createResultNd(rootNd, returnNd, initFilterParam);
        Nv conditionLayoutNv = layoutService.createFilterConditionLayoutNv(conditionNd,initFilterParam.getConditionFdNames());
        conditionLayoutNv.setStringFvByName(ConstDef.FD_NAME_CODE,initFilterParam.getConditionLayoutCode());
        Nv resultLayoutNv = layoutService.createFilterResultLayoutNv(resultNd,initFilterParam.getResultFdNames());
        resultLayoutNv.setStringFvByName(ConstDef.FD_NAME_CODE,initFilterParam.getResultLayoutCode());
        Nv detailLayoutNv = layoutService.createDefaultEntryLayoutNv(initFilterParam.getReturnNdCode());
        detailLayoutNv.setStringFvByName(ConstDef.FD_NAME_CODE,initFilterParam.getDetailLayoutCode());
        Nv conditionNdNv = NvTool.nd2Instance(conditionNd);
        Nv resultNdNv = NvTool.nd2Instance(resultNd);
        Nv menuNv = createMenuNv(initFilterParam);
        Nv filterDefMv = createFilerDefMv(initFilterParam);
        if(conditionNdNv!=null)
            this.nvService.saveNv(CommonInfo.getDefault(),conditionNdNv);
        if ( resultNdNv != null)
            this.nvService.saveNv(CommonInfo.getDefault(),resultNdNv);
        if ( conditionLayoutNv != null)
            this.nvService.saveNv(CommonInfo.getDefault(),conditionLayoutNv);
        if ( resultLayoutNv!=null)
            this.nvService.saveNv(CommonInfo.getDefault(),resultLayoutNv);
        if ( detailLayoutNv!= null)
        this.nvService.saveNv(CommonInfo.getDefault(),detailLayoutNv);
        if (menuNv != null)
            this.nvService.saveNv(CommonInfo.getDefault(),menuNv);
        if ( filterDefMv!= null)
            this.nvService.saveNv(CommonInfo.getDefault(),filterDefMv);
        return filterDefMv;
    }

    private Nv createFilerDefMv(InitFilterParam initFilterParam){
        Nd nd = ndCacheService.getNd(initFilterParam.getReturnNdCode());
        FilterDef filterDef = new FilterDef();
        filterDef.setFilterDefCode(initFilterParam.getCode());
        filterDef.setName(initFilterParam.getName());
        filterDef.setDescription(initFilterParam.getDescription());
        filterDef.setTargetNdCode(initFilterParam.getNdCode());
        filterDef.setReturnNdCode(initFilterParam.getReturnNdCode());
        filterDef.setConditionNdCode(initFilterParam.getConditionNdCode());
        filterDef.setResultNdCode(initFilterParam.getResultNdCode());
        filterDef.setConditionLayoutCode(initFilterParam.getConditionLayoutCode());
        filterDef.setResultLayoutCode(initFilterParam.getResultLayoutCode());
        filterDef.setDetailLayoutCode(initFilterParam.getDetailLayoutCode());
        int filterSerNo = 10;
        int resultSerNo = 10;
        for( InitFdParam initFdParam : initFilterParam.getInitFdParams()) {
            if ( initFdParam.isFilter() ) {
                FilterFd filterFd = new FilterFd();
                filterFd.setNdName(initFdParam.getNdName());
                filterFd.setFdName(initFdParam.getFdName());
                filterFd.setSerNo(filterSerNo);
                filterSerNo += 10;
                filterFd.setLogicalOperator(ConstDef.LOGIC_OPERATION_EQUAL);
                filterDef.getFilterFds().add(filterFd);
            }
            if (initFdParam.isResult()) {
                ResultFd resultFd = new ResultFd();
                resultFd.setNdName(initFdParam.getNdName());
                resultFd.setFdName(initFdParam.getFdName());
                resultFd.setSerNo(resultSerNo);
                resultSerNo += 10;
                filterDef.getResultFds().add(resultFd);
            }
        }
        Nv nv = NdAnnotationUtil.object2Nv(filterDef);
        Nv parentNv = nvService.getNvByCode(CommonInfo.getDefault(),ConstDef.FILTER_FUNCTION,ConstDef.FD_NAME_CODE,ConstDef.ND_CODE_MD);
        nv.setParentId(parentNv.getId());
        return nv;
    }

    private Nv createMenuNv(InitFilterParam initFilterParam){
        String menuCode = initFilterParam.getMenuCode();
        String parentMenuCode = initFilterParam.getParentMenuCode();
        if( StringUtils.isEmpty(menuCode) )
            return null;
        if( StringUtils.isEmpty(parentMenuCode))
            parentMenuCode = "1-1";

        Nv parentNv = nvService.getNvByCode(CommonInfo.getDefault(),parentMenuCode,ConstDef.FD_NAME_CODE,ConstDef.ND_CODE_MENU);
        Nv nv = nvService.initNv(CommonInfo.getDefault(),ConstDef.ND_CODE_MENU);
        nv.setStringFvByName(ConstDef.FD_NAME_CODE, menuCode);
        nv.setStringFvByName(ConstDef.FD_NAME_NAME, initFilterParam.getName());
        nv.setStringFvByName(ConstDef.FD_NAME_DESCRIPTION,initFilterParam.getDescription());
        nv.setStringFvByName(ConstDef.FD_NAME_MODULE_CODE,ConstDef.MODULE_CODE_FILTER);
        nv.setStringFvByName(ConstDef.FD_NAME_MD_CODE,ConstDef.FILTER_FUNCTION);
        nv.setStringFvByName(ConstDef.FD_NAME_MV_CODE,initFilterParam.getCode());
        nv.setBoolFvByName(ConstDef.FD_NAME_LEAF,true);
        nv.setParentId(parentNv.getId());
        return nv;
    }



    private Nd createConditionNd(Nd rootNd, Nd returnNd, InitFilterParam initFilterParam){
        if (StringUtils.isEmpty(initFilterParam.getConditionNdCode()))
            return null;
        Nd newNd = new Nd();
        newNd.setNdCode( initFilterParam.getConditionNdCode());
        newNd.setNdName(returnNd.getNdName() + "CN");
        newNd.setCategory(ConstDef.ND_CATEGORY_DEFUALT);
        newNd.setMinCount(0);
        newNd.setMinCount(999);
        newNd.setCursive(false);
        newNd.setNdDescription(returnNd.getNdDescription()+"条件");
        for(InitFdParam fdParam : initFilterParam.getInitFdParams()){
            if ( !fdParam.isFilter()) continue;
            Nd currentNd = rootNd.findNdByNdName(fdParam.getNdName());
            if (currentNd == null)
                throw new RuntimeException(String.format("找不到ndName:%s的Nd", fdParam.getNdName()));
            Fd fd = currentNd.getFdByName(fdParam.getFdName());
            if ( fd == null )
                throw new RuntimeException(String.format("找不到fdName:%s的Fd", fdParam.getFdName()));

            Fd newFd = new Fd();
            newFd.setFdCode(fdParam.getFdName());
            newFd.setFdName(fdParam.getFdName());
            newFd.setFdDescription(fdParam.getFdDescription());
            newFd.setDataType(fd.getDataType());
            newFd.setMdCode(fd.getMdCode());
            newNd.getFds().add(newFd);
        }
        return newNd;
    }


    private Nd createResultNd(Nd rootNd, Nd returnNd, InitFilterParam initFilterParam){
        if (StringUtils.isEmpty(initFilterParam.getResultNdCode()))
            return null;
        Nd newNd = new Nd();
        newNd.setNdCode( initFilterParam.getResultNdCode());
        newNd.setNdName(returnNd.getNdName() + "RN");
        newNd.setCategory(ConstDef.ND_CATEGORY_DEFUALT);
        newNd.setMinCount(0);
        newNd.setMinCount(999);
        newNd.setCursive(false);
        newNd.setNdDescription(returnNd.getNdDescription()+"结果");
        for(InitFdParam fdParam : initFilterParam.getInitFdParams()){
            if ( !fdParam.isResult()) continue;
            Nd currentNd = rootNd.findNdByNdName(fdParam.getNdName());
            if (currentNd == null)
                throw new RuntimeException(String.format("找不到ndName:%s的Nd", fdParam.getNdName()));
            Fd fd = currentNd.getFdByName(fdParam.getFdName());
            if ( fd == null )
                throw new RuntimeException(String.format("找不到fdName:%s的Fd", fdParam.getFdName()));

            Fd newFd = new Fd();
            newFd.setFdCode(fdParam.getFdName());
            newFd.setFdName(fdParam.getFdName());
            newFd.setFdDescription(fdParam.getFdDescription());
            newFd.setDataType(fd.getDataType());
            newFd.setMdCode(fd.getMdCode());
            newNd.getFds().add(newFd);
        }
        return newNd;
    }

    @Override
    public Nv initFilterFuncParamNv(String targetNdCode, String returnNdCode, String postfix) {
        InitFilterParam param = this.initFilterFuncParam(targetNdCode,returnNdCode,postfix);
        Nv nv = NdAnnotationUtil.object2Nv(param);
        return nv;
    }

    @Override
    public Nv commitFilterFuncNv(Nv initFilterParamNv) {
        InitFilterParam param = NdAnnotationUtil.nv2Object(initFilterParamNv,InitFilterParam.class);
        Nv filterDefNv = this.commitFilterFunc(param);
        return filterDefNv;
    }

}
